<?php

namespace addons\csmitsm\library\xcore\xcflow\utils;

use addons\csmitsm\library\xcore\xcore\utils\XcDaoUtils;
use addons\csmitsm\library\sdnode\xstack\utils\XsDateUtils;
use addons\csmitsm\library\sdnode\xstack\utils\XsJsonUtils;
use addons\csmitsm\library\xcore\xcore\utils\XcDatabaseUtils;
use addons\csmitsm\library\xcore\xcore\utils\XcRequestPathUtils;
use addons\csmitsm\library\xcore\xcore\utils\XcAdminSessionUtils;
use addons\csmitsm\library\xcore\xcore\utils\XcMessageNotifyUtils;

class XcflowInstanceUtils
{

    public static function getXcflowinstance($xcform_id, $xcflowdata_id)
    {
        return XcDaoUtils::getRowBySql(new \app\admin\model\csmitsm\XcflowInstance(), [
            ['xcflow_flowdata_id', '=', $xcflowdata_id],
            ['xcflow_id', '=', $xcform_id]
        ]);
    }

    public static function initRouter($xcflow_id, $xcflowdata_id, $xcformdata)
    {
        $xcflow = XcDaoUtils::getRowById(new \app\admin\model\csmitsm\Xcflow(), $xcflow_id);
        $flowinstance = XcflowInstanceUtils::getXcflowinstance($xcflow_id, $xcflowdata_id);
        if (!$flowinstance) {
            $instance = XcflowGraphDataUtils::createInstance($xcflow_id);
            $fstatus = $instance->getBeginStatus();

            $user_id = XcAdminSessionUtils::getUserId();
            $nickname = XcAdminSessionUtils::getUserNickName();

            $displayfieldvalue = isset($xcformdata[$xcflow->displayfieldcode]) ? $xcformdata[$xcflow->displayfieldcode] : '';

            $flowinstance = XcDaoUtils::create(new \app\admin\model\csmitsm\XcflowInstance(), [
                'xcflow_id' => $xcflow_id,
                'flowtitle' => $xcflow->name . " - {$nickname}",
                'flowtitle' => "[{$xcflow->name}] " . $displayfieldvalue . " - {$nickname}",
                'xcflow_fstatuscode' =>  $fstatus['code'],
                'xcflow_fstatusname' =>  $fstatus['name'],
                'xcflow_toaudit_admin_id' => XcAdminSessionUtils::getUserId(),
                'xcflow_initiator_submittime' => time(),
                'xcflow_initiator_depart_id' => null,
                'xcflow_initiator_company_id' => null,
                'xcflow_initiator_user_id' => $user_id,
                'xcflow_initiator_user_name' => $nickname,
                'xcflow_flowdata_id' => $xcflowdata_id,
                'createtime' => time(),
                'createdate' => XsDateUtils::getCurrentDatestring(),
                'admin_id' => XcAdminSessionUtils::getUserId(),
                'weigh' => 0
            ]);
        }
        static::passRouter($flowinstance, $xcformdata, "", "提交流程");
    }


    // 审核通过, 调用来路由到下个节点
    public static function passRouter($flowinstance, $postFlowdata, $tracecontent, $tracelogstr)
    {
        $id = $flowinstance['xcflow_flowdata_id'];
        $xcform_id = $flowinstance['xcflow_id'];
        $xcform = XcDaoUtils::getRowById(new \app\admin\model\csmitsm\Xcflow(), $xcform_id);
        $xcfieldjsonObj = XcformFieldsUtils::getXcfieldjsonJsonObjectFromXcform($xcform);

        // $from_fstatuscode = $flowinstance['xcflow_fstatuscode'];
        $instance = XcflowGraphDataUtils::createInstance($xcform_id);
        $logic = $instance->getLogicByStatusCode($flowinstance['xcflow_fstatuscode'], "all");
        $target_fstatus = $instance->getStatusById($logic['pass_fstatus_id']);
        $target_logic = $instance->getLogicByStatusCode($target_fstatus['code'], "all");

        $rowFlowdata = XcformDataUtils::getPagedataByTablenameAndRowid($xcform->publishtablename, $xcfieldjsonObj, $flowinstance->xcflow_flowdata_id);

        $target_xcflow_toaudit_type = null;
        $target_xcflow_toaudit_admin_id = null;
        $target_xcflow_toaudit_role_id = null;
        if ($target_logic != null) {
            switch ($target_logic['assigneetype']) {
                case "creator":
                    $target_xcflow_toaudit_type = "admin";
                    $target_xcflow_toaudit_admin_id = $flowinstance['xcflow_initiator_user_id'];
                    break;
                case "admin":
                    $target_xcflow_toaudit_type = "admin";
                    $target_xcflow_toaudit_admin_id = $target_logic['assigneetype_admin_id'];
                    break;
                case "adminfield":
                    $target_xcflow_toaudit_type = "admin";
                    // 如果页面提交了指派字段使用该字段值, 否则使用数据库的保存值
                    $assignadmin = $target_logic['assigneetype_adminfieldcode'];
                    $target_xcflow_toaudit_admin_id = isset($postFlowdata[$assignadmin]) ? $postFlowdata[$assignadmin] : $rowFlowdata[$assignadmin];
                    break;
                case "role":
                    $target_xcflow_toaudit_type = "role";
                    $target_xcflow_toaudit_role_id = $target_logic['assigneetype_role_id'];
                    break;
                case "objselectfield":
                    $target_xcflow_toaudit_type = "admin";
                    // 如果页面提交了指派字段使用该字段值, 否则使用数据库的保存值
                    $assignflowfield = $target_logic['assigneetype_objselect_flowfieldcode'];
                    $selectFlowFieldvalue = isset($postFlowdata[$assignflowfield]) ? $postFlowdata[$assignflowfield] : $rowFlowdata[$assignflowfield];
                    $fieldItem = XcformFieldsUtils::getXcfieldjsonJsonItemFromXcformByFieldcode($xcform, $target_logic['assigneetype_objselect_flowfieldcode']);
                    $target_table_row =  XcDatabaseUtils::getRowById($fieldItem['fieldjsonObj']['xcform_base_selecttablefield']['tablename'], $selectFlowFieldvalue);
                    $target_xcflow_toaudit_admin_id = $target_table_row[$target_logic['assigneetype_objselect_relateadminfieldcode']];
                    break;
            }
        }

        $xcformdata = null;
        if (true) {
            $xcformdata = XcformDataUtils::updateData($xcform->publishtablename, $xcfieldjsonObj, $flowinstance->xcflow_flowdata_id, $postFlowdata);
        }

        $flowinstancetitle = XcAdminSessionUtils::getUserNickName() . " " . $tracelogstr;
        XcDaoUtils::create(new \app\admin\model\csmitsm\XcflowInstancetrace(), [
            'xcflow_instance_id' => $flowinstance['id'],
            'title' => $flowinstancetitle,
            'content' => $tracecontent,
            'images' => '',
            'operate' => 'pass',
            'from_fstatuscode' => $flowinstance['xcflow_fstatuscode'],
            'from_fstatusname' => $flowinstance['xcflow_fstatusname'],
            'target_fstatuscode' => $target_fstatus['code'],
            'target_fstatusname' => $target_fstatus['name'],
            'xcflow_toaudit_type' => $target_xcflow_toaudit_type,
            'xcflow_toaudit_admin_id' => $target_xcflow_toaudit_admin_id,
            'xcflow_toaudit_role_id' => $target_xcflow_toaudit_role_id,
            'trace_submittime' => time(),
            'trace_depart_id' => null,
            'trace_company_id' => null,
            'trace_admin_id' => XcAdminSessionUtils::getUserId(),
            'trace_admin_name' => XcAdminSessionUtils::getUserNickName(),
            'flowfieldjson' => XsJsonUtils::jsonToString($postFlowdata),
            'createtime' => time(),
            'createdate' => XsDateUtils::getCurrentDatestring(),
            'admin_id' => XcAdminSessionUtils::getUserId(),
            'weigh' => 0,
        ]);

        // create mdmdata while xcflow_endstatus
        $mdmData = null;
        if (true) {
            $endStatus = $instance->getEndStatus();
            if ($endStatus['code'] == $target_fstatus['code']) {
                $mdmData = XcflowToMdmUtils::createOrUpdateFromXcflowdata($xcform_id, $xcformdata);
            }
        }

        if (true) {
            $flowinstance->save([
                'xcflow_fstatuscode' =>  $target_fstatus['code'],
                'xcflow_fstatusname' =>  $target_fstatus['name'],
                'xcflow_mdmdata_id' => isset($mdmData['id']) ? $mdmData['id'] : null,
                'xcflow_toaudit_type' => $target_xcflow_toaudit_type,
                'xcflow_toaudit_admin_id' => $target_xcflow_toaudit_admin_id,
                'xcflow_toaudit_role_id' => $target_xcflow_toaudit_role_id,
                'updatetime' => time(),
                'updatedate' => XsDateUtils::getCurrentDatestring(),
            ]);
        }

        // message notify
        if (true) {
            $notify_confignames = ["email" => "xcflow_emailtpl", "mobile" => "xcflow_mobiletpl"];
            $notify_title = "流程待处理通知: {$flowinstancetitle}";
            $notify_data = [
                'title'=>$flowinstancetitle,
                'url'=>XcRequestPathUtils::urlAdmin("/csmitsm/xcmyflowinstance/index?open_xcflowinstance_id=".$flowinstance['id']."&ref=addtabs"),
            ];
            if ($target_xcflow_toaudit_type == 'role') {
                XcMessageNotifyUtils::notifyAdminRole($target_xcflow_toaudit_role_id, $notify_confignames, "工作流待审核", $notify_title, $notify_data);
            } else if ($target_xcflow_toaudit_type == 'admin') {
                XcMessageNotifyUtils::notifyAdmin($target_xcflow_toaudit_admin_id, $notify_confignames, "工作流待审核", $notify_title, $notify_data);
            }
        }
    }

    // 审核退回, 调用来路由到下个节点
    public static function rejectRouter($flowinstance, $xcflowdata, $tracecontent)
    {
        $xcform_id = $flowinstance['xcflow_id'];

        $target_fstatus_code = null;
        $target_fstatus_name = null;
        $xcflow_toaudit_type = null;
        $xcflow_toaudit_admin_id = null;
        $xcflow_toaudit_role_id = null;
        if (true) {
            $instance = XcflowGraphDataUtils::createInstance($xcform_id);
            $logic = $instance->getLogicByStatusCode($flowinstance['xcflow_fstatuscode'], "all");
            switch ($logic['rejecttype']) {
                case "creator":
                    $fstatus = $instance->getBeginStatus();
                    $target_fstatus_code = null;
                    $target_fstatus_name = null;
                    $xcflow_toaudit_type = "admin";
                    $xcflow_toaudit_admin_id = $flowinstance['xcflow_initiator_user_id'];
                    $xcflow_toaudit_role_id = null;
                    break;
                case "last":
                    // search last_pass_operate from fa_csmitsm_xcflow_instancetrace 
                    $lastInstancetrace = XcDaoUtils::getRowBySql(new \app\admin\model\csmitsm\XcflowInstancetrace(), [
                        ['operate', '=', 'pass'],
                        ['xcflow_instance_id', '=', $flowinstance->id],
                        ['target_fstatuscode', '=', $flowinstance['xcflow_fstatuscode']]
                    ], null, 'id desc');
                    // to last audit_admin
                    if ($lastInstancetrace) {
                        $target_fstatus_code = $lastInstancetrace['from_fstatuscode'];
                        $target_fstatus_name = $lastInstancetrace['from_fstatusname'];
                        $xcflow_toaudit_type = 'admin';
                        $xcflow_toaudit_admin_id = $lastInstancetrace['trace_admin_id'];
                        $xcflow_toaudit_role_id = null;
                    } else {
                        // default to creator while error_data_logic 
                        $fstatus = $instance->getBeginStatus();
                        $target_fstatus_code = $fstatus['code'];
                        $target_fstatus_name = $fstatus['name'];
                        $xcflow_toaudit_type = "admin";
                        $xcflow_toaudit_admin_id = $flowinstance['xcflow_initiator_user_id'];
                        $xcflow_toaudit_role_id = $flowinstance['xcflow_toaudit_role_id'];
                    }
                    break;
            }
        }

        $flowinstancetitle = XcAdminSessionUtils::getUserNickName() . " 审核退回";
        $trace = new \app\admin\model\csmitsm\XcflowInstancetrace();
        $trace->create([
            'xcflow_instance_id' => $flowinstance['id'],
            'title' => $flowinstancetitle,
            'content' => $tracecontent,
            'images' => '',
            'operate' => 'reject',
            'from_fstatuscode' => $flowinstance['xcflow_fstatuscode'],
            'from_fstatusname' => $flowinstance['xcflow_fstatusname'],
            'target_fstatuscode' => $target_fstatus_code,
            'target_fstatusname' => $target_fstatus_name,
            'xcflow_toaudit_type' => $xcflow_toaudit_type,
            'xcflow_toaudit_admin_id' => $xcflow_toaudit_admin_id,
            'xcflow_toaudit_role_id' => $xcflow_toaudit_role_id,
            'trace_submittime' => time(),
            'trace_depart_id' => null,
            'trace_company_id' => null,
            'trace_admin_id' => XcAdminSessionUtils::getUserId(),
            'trace_admin_name' => XcAdminSessionUtils::getUserNickName(),
            'flowfieldjson' => null,
            'weigh' => 0,
        ]);

        $flowinstance->save([
            'xcflow_fstatuscode' => $target_fstatus_code,
            'xcflow_fstatusname' =>  $target_fstatus_name,
            'xcflow_toaudit_type' => $xcflow_toaudit_type,
            'xcflow_toaudit_admin_id' => $xcflow_toaudit_admin_id,
            'xcflow_toaudit_role_id' => $xcflow_toaudit_role_id,
        ]);

        // message notify
        if (true) {
            $notify_confignames = ["email" => "xcflow_emailtpl", "mobile" => "xcflow_mobiletpl"];
            $notify_title = "流程退回通知: {flowtitle}";
            $notify_data = [
                'title'=>$flowinstancetitle,
                'url'=>XcRequestPathUtils::urlAdmin("/csmitsm/xcmyflowinstance/index?open_xcflowinstance_id=".$flowinstance['id']."&ref=addtabs"),
                //'url'=>XcRequestPathUtils::urlAdmin("/csmitsm/xcmyflowinstance/showxcformpage?xcform_id={$xcform_id}&id=".$xcflowdata["id"]),
            ];
            if ($xcflow_toaudit_type == 'admin') {
                XcMessageNotifyUtils::notifyAdmin($xcflow_toaudit_admin_id, $notify_confignames, "工作流退回通知", $notify_title, $notify_data);
            }
        }
    }
}
